package wiki.liven.web;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import wiki.liven.Exception.RepeatkillException;
import wiki.liven.Exception.SeckillClosedException;
import wiki.liven.dto.Exposer;
import wiki.liven.dto.SecKillExcution;
import wiki.liven.dto.SeckillResult;
import wiki.liven.euum.SeckillEunm;
import wiki.liven.pojo.Seckill;
import wiki.liven.service.SeckillService;

import java.util.Date;
import java.util.List;

/**
 * Created by leven on 2016/10/30.
 * 秒杀业务
 * *
 *
 * public wiki.liven.dto.SeckillResult<wiki.liven.dto.SecKillExcution> wiki.liven.web.SeckillController.excution(java.lang.Long,java.lang.String,java.lang.String)
    to {[/seckill],methods=[POST],produces=[application/json;charset=UTF-8]}:
 There is already 'seckillController' bean method

 java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'seckillController' method
 public java.lang.String wiki.liven.web.SeckillController.detail(java.lang.Long,org.springframework.ui.Model)
 to {[/seckill],methods=[GET]}: There is already 'seckillController' bean method
 public java.lang.String wiki.liven.web.SeckillController.list(org.springframework.ui.Model) mapped.

 Loading XML bean definitions from class path resource [spring/spring-web.xml]
 十一月 07, 2016 11:14:12 下午 org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping register
 信息: Mapped "{[/seckill],methods=[GET]}" onto public java.lang.String wiki.liven.web.SeckillController.list(org.springframework.ui.Model)
 十一月 07, 2016 11:14:12 下午 org.springframework.web.context.support.XmlWebApplicationContext refresh
 警告: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException:
 Error creating bean with name 'org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping': Invocation of init method failed;
 nested exception is java.lang.IllegalStateException: Ambiguous mapping. Cannot map 'seckillController' method
 public java.lang.String wiki.liven.web.SeckillController.detail(java.lang.Long,org.springframework.ui.Model)
 to {[/seckill],methods=[GET]}: There is already 'seckillController' bean method
 public java.lang.String wiki.liven.web.SeckillController.list(org.springframework.ui.Model) mapped.
 */
@Controller
public class SeckillController {

    @Autowired
    private SeckillService seckillService;

    private final Logger logger = LoggerFactory.getLogger(SeckillController.class);


    /**
     * 进入秒杀产品列表页面
     * @param model
     * @return
     */
    @RequestMapping(name = "/list",method = RequestMethod.GET)
    public String list(Model model){
        List<Seckill> seckills = seckillService.findAll();
        model.addAttribute("list",seckills);
        return "list";
    }

    /**
     * 进入秒杀产品详细页面
     * @param seckillId
     * @param model
     * @return
     */
    @RequestMapping(name = "/{seckillId}/detail",method = RequestMethod.GET)
    public String detail(@PathVariable("seckillId") Long seckillId,Model model){
        if(null==seckillId){
            return "redirect:/seckill/list";
        }
        Seckill seckill = seckillService.findOne(seckillId);
        if (null==seckill){
            return "redirect:/seckill/list";
        }
        model.addAttribute("seckill",seckill);
        return "detail";
    }

    /**
     * 暴露秒杀地址
     * @param seckillId
     * @return
     */
    @RequestMapping(name = "/{seckillId}/exposer",method = RequestMethod.POST, produces = {"application/json;charset=UTF-8"})
    @ResponseBody
    public SeckillResult<Exposer> exposer(Long seckillId){
        SeckillResult<Exposer> result = null;
        try{
            Exposer exposer = seckillService.exportSecKillUrl(seckillId);
            result = new SeckillResult<Exposer>(exposer,true);
        }catch (Exception e){
            logger.error(e.getMessage(),e);
            result = new SeckillResult<Exposer>(e.getMessage(),false);
        }
        return result;
    }


    /**
     * 执行秒杀
     * @param seckillId
     * @param md5
     * @param userPhone
     * @return
     */
    @RequestMapping(name = "/{seckillId}/{md5}/excution",method = RequestMethod.POST,produces = {"application/json;charset=UTF-8"})
    public @ResponseBody SeckillResult<SecKillExcution> excution(@PathVariable("seckillId") Long seckillId,
                                                   @PathVariable("md5") String md5,
                                                   @CookieValue(name = "phone",required = false) String userPhone){
        if(null == userPhone){
            return new SeckillResult<SecKillExcution>("当前用户没有注册",false);
        }
        SeckillResult<SecKillExcution> result = null;
        try{
            SecKillExcution secKillExcution = seckillService.executeSecKill(seckillId,userPhone,md5);
            result = new SeckillResult<SecKillExcution>(secKillExcution,true);
            return result;
        }catch (RepeatkillException e){
            SecKillExcution secKillExcution = new SecKillExcution(seckillId, SeckillEunm.REPEAT_KILL);
            return new SeckillResult<SecKillExcution>(secKillExcution,false);
        }catch (SeckillClosedException e){
            SecKillExcution secKillExcution = new SecKillExcution(seckillId, SeckillEunm.END);
            return new SeckillResult<SecKillExcution>(secKillExcution,false);
        }catch (Exception e){
            logger.error(e.getMessage(),e);
            SecKillExcution secKillExcution = new SecKillExcution(seckillId, SeckillEunm.INNER_ERROR);
            return new SeckillResult<SecKillExcution>(secKillExcution,false);
        }
    }

    /**
     * 获取系统时间
     * @return
     */
    @RequestMapping(name = "/seckill/now",method = RequestMethod.GET,produces = {"application/json;charset=UTF-8"})
    public @ResponseBody SeckillResult<Long> getNow(){
        Date now = new Date();
        return new SeckillResult<Long>(now.getTime(),true);
    }


}
